/**
 *
 * $Id: CoordinateDriveTypes.i,v 1.4 2009-11-26 15:42:17 ttaipalu Exp $
 *
 * \file CoordinateDriveTypes.i
 * \brief MaCI - ptyhon wrap for Coordinate drive Interface Type definition header
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 * \author Tapio Taipalus <tapio.taipalus@tkk.fi>
 *
 * 
 */

%{
#include <inttypes.h>
#include "timestamp.hpp"
#include "CoordinateDriveTypes.hpp"
%}
%include "inttypes.i"
%include "../common/timestamp.i"
namespace MaCI {

  /** MaCI - CoordinateDrive interface.
   *
   * This namespace contains all types, methods and helper classes
   * for implementing a CoordinateDrive interface for MaCI.
   */
  namespace CoordinateDrive {

    /** CoordinateDrive element types.
     * 
     * This enumeration defines the available elements for Coordinate interface.
     *
     */
    enum ECoordinateDriveType { 
      KTypeUnknown                    = -1, ///< Unknown type
      KTypeCoordinate2D               = 0,  ///< Contains TCoordinate2D
      KTypeTargetLimitDistance        = 1,  ///< Contains TTargetLimitDistance
      KTypeDriveMode                  = 2,  ///< Contains TDriveMode
      KTypeCoordinateHeader           = 3,  ///< Contains TCoordinateHeader
      KTypeDriveModeHeader            = 4,  ///< Contains TDriveModeHeader
      KTypeTimestamp                  = 5,  ///< Contains MaCI::Common::TTimestamp
      KTypeSpeed                      = 6,  ///< Contains TSpeed
      KTypeCommand                    = 9   ///< Contains TCommand
    };

    /** CoordinateDrive commands.
     *
     * CoordinateDrive commands for the 'TCommand' structure. Defined in global
     * 'CoordinateDrive' namespace because otherwise l^Husers would complain :)
     */
    enum ECoordinateDriveCommand { 
      KCommandUnknown                   = 0,  ///< Unkown command
      KCommandInitialize                = 1,  ///< Reset
      KCommandSetCoordinate2D           = 2,  ///< Set Coordinate2D on device
      KCommandRemoveCoordinates         = 3,  ///< Removes all the coordinates
      KCommandSetStart                  = 4,  ///< Start driving to target
      KCommandSetStop                   = 5,  ///< Stops driving to target
      KCommandSetDriveMode              = 6,  ///< Set coordinatedrive mode
      KCommandUnsetDriveMode            = 7,  ///< Unset coordinatedrive mode
      KCommandContinue                  = 8,  ///< Continue, when arrived at a wait point
      KCommandArrivedToPoint            = 9,  ///< Arrived to point event
      KCommandGetCoordinates            = 10, ///< Get Coordinates
      KCommandGetDrivingModes           = 11, ///< Get Driving modes
      KCommandArrivedToPointEvent       = 12, ///< Arrived to point event, Use this when sending event!
      KCommandGetCoordinatesReply       = 10, ///< Get Coordinates reply, Use this when sending reply!
      KCommandGetDrivingModesReply      = 11, ///< Get Driving modes reply, Use this when sending reply!
      KCommandGetPlanFromTo             = 13, ///< Get plan points between two coordinates 
      KCommandGetPlanFromToReply        = 13, ///< Get plan points REPLY between two coordinates 
      KCommandCoordinatesEvent          = 14, ///< Event for sending all coordinates set to server
      KCommandSetDrivingSpeed           = 15, ///< Set driving speed .
      KCommandGetMaxDrivingSpeed        = 16, ///< Get maximum driving speed
      KCommandGetMaxDrivingSpeedReply   = 16, ///< Get maximum driving speed reply, Use this when sending reply!
      KCommandUnableToDriveToCoordinate = 17, ///< Command to tell, that the coordinatedrive module can't drive coordinate.
      KCommandCalculating               = 18, ///< Command to tell, that the planner is calculating
      KCommandPathReady                 = 19  ///< Command to tell, that the planner has calculated the plan
    };

    /** Coordinate drive mode
     * 
     * Defines how coordinateDrive behaves. At the beginning all modes are unset.
     * When no modes are set CoordinateDrive tries to drive toward the first point. When
     * coordinate is reached, it deletes the point at start to go toward next point.
     * CoordinateDrive don't drive backward and turn toward coordinate while driving. It stop
     * driving when it's near enough the coordinate(The wanted distance can be set) and there's 
     * not any target left.
     *
     *
     * KModeUseReverse          When KModeUseReverse is set coordinateDrive drives also 
     *                          backward if the given coordinate is behind the robot.
     *
     * KModeTurnFirstTowardGoal When KModeDriveStraight is set, coordinateDrive first turn
     *                          toward and then drive straight to point.
     *
     * KModeUseAngle            When KModeUseAngle is set, the ending angle of the robot can be 
     *                          defined
     *
     * KModePathDriving         When KModePathDriving is set, CoordinateDrive don't delete the given
     *                          points and drive them 
     * 
     */
    enum ECoordinateDriveMode{
      KModeUseReverse           = 0, ///< Uses negative speed value if point is behind the robot
      KModeTurnFirstTowardGoal  = 1, ///< Turn first toward the target and the drives to target
      KModeUseAngle             = 2,  ///< Uses the angle value to define the heading at the target
      KModePathDriving          = 3, ///< Driving path driving
		  KModeInitializing         = 4, ///< Used while the Module initializes itself
			KModeEmergency            = 5, ///< Used if the module meets an emergency state (or is set to it from outside)
			KModeRecovery             = 6, ///< Used module tries to recover from emergency
    };



    /** 2D Coordinate.
     *
     * Defines a structure for representing a 2D Coordinate. 2D-Coordinate
     * includes the (\p x,\p y) position , \p heading and \p isDifferential. Position and heading
     * units are SI, so coordinates are specified as meters, and heading as
     * radians. Coordinate system is defined as follows:
     * - angles are positive CCW
     * - zero angle is towards the X axis
     * - positive movement moves by the posivite X axis
     * - 'turning left' means turning towards positive Y axis
     *
     * \p isDifferential is for defining if the given coordinate is differential or global
     * \p isPathTarget is for defining if the given coordinate is a path or a normal target point
     * \p isWaitPoint is for defining if the given coordinate is a wait point,
     */
    struct TCoordinate2D
    {
      TCoordinate2D(const float aX = 0.0, 
		    const float aY = 0.0, 
		    const float aA = 0.0,
		    const uint32_t aIsDifferential = 0,
		    const uint32_t aIsPathTarget = 0,
		    const uint32_t aIsWaitPoint = 0)
        : x(aX),
          y(aY),
	  a(aA),
          isDifferential(aIsDifferential),
	  isPathTarget(aIsPathTarget),
	  isWaitPoint(aIsWaitPoint){}
      float x;                 ///< X-axis in meters
      float y;                 ///< Y-axis in meters
      float a;                 ///< angle
      uint32_t isDifferential; ///< define if the coordinate is differential or global 
      uint32_t isPathTarget;   ///< define if the coordinate is a path or normal target point
      uint32_t isWaitPoint;    ///< Defines if the coordinate is a wait point. It is checked 
                               /// only when given a path coordinate
    };

    /** Target limit distance
     * 
     * Defines the distance how near the goal coordinateDrive goes to be at target
     *
     */
    struct TTargetLimitDistance{
      TTargetLimitDistance(const float aLimit = 0.0) 
	:limit(aLimit){}

      float limit;             ///The limit distance when arrived to target
    
    };

    /** CoordinateDrive interface command.
     *
     * Describes a Command for the CoordinateDrive interface. 
     * Commands may required additional dataelements, 
     * and are specified in the descriptions of the commands.
     */
    struct TCommand {
      TCommand(ECoordinateDriveCommand aCmd = KCommandUnknown) 
	: cmd(aCmd) {}
      
      uint32_t cmd; ///< Command value
    };

    /**
     * Struct for defining the ECoordinateDriveMode.
     *
     */
    struct TDriveMode {
      TDriveMode(ECoordinateDriveMode aMode)
	: mode(aMode){}

      uint32_t mode; ///< Mode value
    };

    /**
     * Struct for sending multiple coordinates. This header tells how
     * many Coordinates are coming after this header.
     */
    struct TCoordinateHeader{
      TCoordinateHeader(const unsigned int aCoordinateCount):
	coordinateCount(aCoordinateCount){}

      uint32_t coordinateCount;

    };

    /**
     * Struct for sending multiple TDriveMode-struct. This header tells how
     * many DriveMode are coming after this header.
     */
    struct TDriveModeHeader{
      TDriveModeHeader(const unsigned int aDriveModeCount):
	driveModeCount(aDriveModeCount){}

      uint32_t driveModeCount;

    };
    /**
     * Struct for storing information to send reply messages
     */
    struct TReplyInfo {
      TReplyInfo(int aSenderId, int aMsgId) :
	senderId(aSenderId),
	msgId(aMsgId){}
      
      int senderId;
      int msgId;
    };
	
    /**
     * Struct for storing speed information
     */
    struct TSpeed{
      TSpeed(float aSpeed = 0.0,float aAngularSpeed= 0.0)
        :speed(aSpeed),
         angularSpeed(aAngularSpeed){}

      float speed;
      float angularSpeed;
    };
	
}

}

